#include "visualisation.h"
#include "myapplication.h"
#include <iostream>

using namespace std;
using namespace Ogre;


Visualisation::Visualisation() : myApp(NULL)
{
	construction_finie=false;
	decalage=0;
}

Visualisation::~Visualisation()
{
	delete myApp;
}

void Visualisation::setApplication(MyApplication * m)
{
	myApp = new MyApplication;
	myApp = m;
}

//fonction permettant d'afficher un message dans le panneau d'affichage
void Visualisation::afficherMessage ( string s )
{
    myApp->setDebugOverlay(s) ;;
}

//fonction pour tracer une ligne entre 2 objets
void Visualisation::ligne(SceneNode* sceneN,Vector3 pos1, Vector3 pos2) {

//DEBUG
	/*ostringstream oss;
	oss<<"pos1 :"<<pos1;
	oss<<"pos2 :"<<pos2<<endl;
	debug+=("DEBUG ligne");
	debug+=oss.str();*/

	ostringstream ligne;
	ostringstream lignenode;

	ligne<<"Ligne"<<myApp->getNbLignes();
	lignenode<<"LigneNode"<<myApp->getNbLignes();

    ManualObject* myManualObject =  myApp->getSceneManager()->createManualObject(ligne.str());
    SceneNode* myManualObjectNode = sceneN->createChildSceneNode(lignenode.str());


    myManualObject->begin("Color/Black" , Ogre::RenderOperation::OT_LINE_LIST);
    myManualObject->position(pos1);
    myManualObject->position(pos2);
    myManualObject->end();

    myManualObjectNode->attachObject(myManualObject);

    myApp->setNbLignes((myApp->getNbLignes())+1);
}

//on créé le noeud racine de l'application sur lequel tous les autres noeuds seront rattachés
void Visualisation::creerRacine(string nom, string nomMesh, Vector3 echelle)
{
    Entity * ent = myApp->getSceneManager()->createEntity(nom,nomMesh);
    SceneNode* node = myApp->getSceneManager()->getRootSceneNode()->createChildSceneNode(nom);
    node->scale(echelle);
    node->attachObject(ent);
	//on recupere le rayon du premier cube
    myApp->setRatio(myApp->getSceneManager()->getEntity(nom)->getBoundingRadius());
	//selection initiale
    myApp->setSelected(nom);
	this->racine=node;
}

void Visualisation::creerEntite(string nom, string nomMesh, Vector3 position)
{
	Entity * ent = myApp->getSceneManager()->createEntity(nom,nomMesh);
    SceneNode* node = this->racine->createChildSceneNode(nom,(position*FACTOR));
	node->scale(Vector3(SCALE,SCALE,SCALE));
    node->attachObject(ent);
}

//repartit les elements horizontalement dans l'espace
//on fournira uniquement des espacements impaires
void Visualisation::repartirAbscisse(int profondeur, vector<Vector3> &vectPositions)
{
	vectPositions[0]=Vector3(getDecalage(),profondeur*VER_SPACE,0);
	for (unsigned int i=1;i<vectPositions.size();i++)
	{
		vectPositions[i] = Vector3((vectPositions[0]).x + i*(HOR_SPACE+1),profondeur*VER_SPACE,0);
	}
	//mise a jour du decalage
	decalage=((int)(vectPositions[vectPositions.size()-1].x))+HOR_INTERSPACE;

//DEBUG
	/*ostringstream oss;
	oss<<(int)vectPositions[vectPositions.size()-1].x<<endl;
	afficherMessage(oss.str());*/
}

//affiche les fils d'un repertoire
void Visualisation::afficherFils(Folder * dossierPere, Vector3 positionPere,vector<Vector3> &vectPositions)
{
		unsigned int i;
		unsigned int fin_fichier_gauche;
		//affichage de la moitie des fichiers sur la gauche
		for (i=0,fin_fichier_gauche=0; i< (dossierPere->getLeftFiles()).size();i++,fin_fichier_gauche++)
		{
			creerEntite((dossierPere->getFileNo(i))->getNom(),"SphereRed.mesh",vectPositions[i]);
		}
		//affichage des sous-repertoires au centre
		for (unsigned int j=0; j< (dossierPere->getOrderedSubfolders()).size();i++,j++)
		{
			creerEntite((dossierPere->getFolderNo(j))->getNom(),"CubeGreen.mesh",vectPositions[i]);
		}
		//affichage de la moitie des fichiers sur la droite
		for (unsigned int k=0; k< (dossierPere->getRightFiles()).size();i++,k++)
		{
			creerEntite((dossierPere->getFileNo(k+fin_fichier_gauche))->getNom(),"SphereBlue.mesh",vectPositions[i]);
		}
} 

void Visualisation::afficherPartieGaucheFils(Folder * dossierPere,vector<Vector3> &vectPositions)
{
	for (unsigned int i=0; i< (dossierPere->getLeftFiles()).size() ; i++)
	{
		creerEntite((dossierPere->getFileNo(i))->getNom(),"SphereYellow.mesh",vectPositions[i]);
	}
}

void Visualisation::afficherPartieDroiteFils(Folder * dossierPere,vector<Vector3> &vectPositions)
{
	int nbdec = (dossierPere->getLeftFiles()).size();
	for (unsigned int i=0; i< (dossierPere->getRightFiles()).size() ; i++)
	{
		creerEntite((dossierPere->getFileNo(i+nbdec))->getNom(),"SphereGreen.mesh",vectPositions[i]);
	}
}

void Visualisation::creerLiensFils(Vector3 position, vector<Vector3> &vectPositions) 
{
	for (unsigned int i=0;i<vectPositions.size();i++)
	{	
		ligne(getRacine(),position,vectPositions[i]);
	}
}

Vector3 Visualisation::positionnerElements(Folder * f)
{
//DEBUG
	ostringstream oss;

	//on recupere les sous-repertoires
	int ma_position_x,g,d;
	Vector3 maPosition; 
	vector<Folder *> repertoiresFils(f->getOrderedSubfolders().size());
	vector<Vector3> vectRepertoireFils(f->getOrderedSubfolders().size());
	vector<Vector3> vectPosFils(f->objCount);
	vector<Vector3> vectPosFilsGauche(f->getLeftFiles().size());
	vector<Vector3> vectPosFilsDroite(f->getLeftFiles().size());

	if ( (f->queDesFilsTerminaux) )
	{
		//on recupere la position a laquelle doit se placer les fils
		repartirAbscisse((f->getProfondeur())+1,vectPosFils);

//DEBUG
		/*for (unsigned int i=0;i<vectPosFils.size();i++)
		{
			oss<<"ma position "<<i<<" : "<<vectPosFils[i]<<endl;
		}*/

		//on calcul la position du pere en fonction de la position des fils
		g = (int)vectRepertoireFils[0].x;
		d = (int)vectRepertoireFils[vectRepertoireFils.size()-1].x;
		ma_position_x= g +(d-g)/2;
		maPosition=Vector3(ma_position_x,(f->getProfondeur())*VER_SPACE,0);
		ma_position_x=(int)vectPosFils[0].x+((((int)vectPosFils[vectPosFils.size()-1].x)-((int)vectPosFils[0].x))/2);

		maPosition=Vector3(ma_position_x,(f->getProfondeur())*VER_SPACE,0);

//DEBUG
		/*oss<<"ma position :"<<maPosition<<endl;
		afficherMessage(oss.str());
		oss<<f->getProfondeur()<<f->getNom();
		debug+="prof avant"+oss.str()+"\n";*/


		//on affiche le pere 	
		creerEntite(f->getNom(),"CubeYellow.mesh",maPosition);	
		//on affiche les fils
		afficherFils(f,maPosition,vectPosFils);
		//creation des liens avec les fils
		creerLiensFils(maPosition,vectPosFils);
	}
	else
	{
		repertoiresFils = (f->getOrderedSubfolders());

		//affichage des fichiers gauches	
		repartirAbscisse((f->getProfondeur())+1,vectPosFilsGauche);
		afficherPartieGaucheFils(f,vectPosFilsGauche);

		for (unsigned int i=0; i<repertoiresFils.size() ; i++)
		{
			vectRepertoireFils[i]=(positionnerElements(repertoiresFils[i]));
		}

//DEBUG
		/*oss<<repertoiresFils.size();
		debug+="taille repFils : ---"+oss.str()+"---\n";
		oss<<vectRepertoireFils.size();
		debug+="taille vectPosFils apres: ---"+oss.str()+"---\n";*/
	
		g = (int)vectRepertoireFils[0].x;
		d = (int)vectRepertoireFils[vectRepertoireFils.size()-1].x;
		ma_position_x= g +(d-g)/2;
		maPosition=Vector3(ma_position_x,(f->getProfondeur())*VER_SPACE,0);

		//affichage des fichiers droits
		repartirAbscisse((f->getProfondeur())+1,vectPosFilsDroite);
		afficherPartieDroiteFils(f,vectPosFilsDroite);
	
//DEBUG
		//oss<<f->getProfondeur()<<f->getNom();
		//debug+="prof racine"+oss.str()+"\n";

		creerEntite(f->getNom(),"CubeRed.mesh",maPosition);	

		creerLiensFils(maPosition,vectPosFilsGauche);	
		creerLiensFils(maPosition,vectPosFilsDroite);	
		creerLiensFils(maPosition,vectRepertoireFils);			
	}
	return maPosition;
}

void Visualisation::creerRepresentationGraphique(char * nomOv)
{
	myApp->setRatio(100);

	this->racine=myApp->getSceneManager()->getRootSceneNode()->createChildSceneNode("SceneRacine");

	Folder * f = new Folder(nomOv,0); 
	
	positionnerElements(f);

	afficherMessage(debug);

	construction_finie=true;
}

//getters
SceneNode * Visualisation::getNoeud(String name)
{
	return myApp->getSceneManager()->getSceneNode(name);
}

SceneNode * Visualisation::getRacine()
{
	return this->racine;
}

int Visualisation::getDecalage()
{
	return decalage;
}

void Visualisation::setDecalage(int i)
{
	decalage=i;
}

bool Visualisation::getConstructionFinie()
{
	return construction_finie;
}
